#ifndef __FLOOR__HPP__
#define __FLOOR__HPP__

// Floor
struct Floor {
  static std::string name() { return "FLOOR"; }
  // constexpr only if proper definition using actual modulo and remainder
  // static int apply (int l, int h) { 
  //   return floor(((double)(l))/((double)(h))); 
  // }
  constexpr static int apply (int l, int h) { 
    return (((l > 0 && h < 0) || (l < 0 && h > 0)) && (l % h) != 0) ? l/h-1 : l/h;
  }
};

template< class A>
constexpr Expression<BinaryExpression<Expression<A>, Expression<ConstantTerm>, Floor> >
floor(Expression<A> a, int const & b)
{
  typedef BinaryExpression <Expression<A>, Expression<ConstantTerm>, Floor> ExprT;
  return Expression<ExprT>(ExprT(a,Expression<ConstantTerm>(b)));
}

template <int PLACE>
constexpr Expression<BinaryExpression<Expression<VariableTerm<PLACE> >, Expression<ConstantTerm>, Floor> >
floor(VariableTerm<PLACE> const & b, ConstantTerm const & a) {
  typedef BinaryExpression <Expression<VariableTerm<PLACE> >, Expression<ConstantTerm>, Floor> ExprT;
  return Expression<ExprT>(ExprT(Expression<VariableTerm<PLACE> >(b), Expression<ConstantTerm>(a)));
}
constexpr Expression<BinaryExpression<Expression<ConstantTerm>, Expression<ConstantTerm>, Floor> >
floor(ConstantTerm const & b, ConstantTerm const & a) {
  typedef BinaryExpression <Expression<ConstantTerm>, Expression<ConstantTerm>, Floor> ExprT;
  return Expression<ExprT>(ExprT(Expression<ConstantTerm>(b), Expression<ConstantTerm>(a)));
}
#endif //__FLOOR__HPP__
